"""
Playwright 反检测配置脚本
参考 undetected-chromedriver 的实现，为 Playwright 提供类似的反检测功能
"""

# ✅ CDP 反检测脚本（用于 Page.addScriptToEvaluateOnNewDocument）
# 这个版本已被验证能通过 Fingerprint.com 和 bot-detector.rebrowser.net 的检测
# 关键：使用 CDP 在底层注入，比 add_init_script 更早执行，更难被检测
CDP_STEALTH_SCRIPT = '''
    // ✅ 完整反检测脚本（已验证能通过 Fingerprint.com）
    // 1. 隐藏 navigator.webdriver（尝试删除，如果失败则由启动参数处理）
    try {
        delete navigator.__proto__.webdriver;
        delete navigator.webdriver;
    } catch(e) {}
    
    // 2. 模拟 Chrome runtime
    if (!window.chrome) {
        window.chrome = {};
    }
    if (!window.chrome.runtime) {
        window.chrome.runtime = {
            PlatformOs: { MAC: 'mac', WIN: 'win', ANDROID: 'android', CROS: 'cros', LINUX: 'linux' },
            PlatformArch: { ARM: 'arm', X86_32: 'x86-32', X86_64: 'x86-64' }
        };
    }
    
    // 3. 设置 navigator 属性（对 Fingerprint.com 有效，虽然会被 Object.getOwnPropertyNames 检测到，
    //    但 Fingerprint.com 不使用这个方法，bot-detector.rebrowser.net 也能通过）
    Object.defineProperty(navigator, 'languages', {
        get: () => ['zh-CN', 'zh', 'en-US', 'en'],
        configurable: true
    });
    
    Object.defineProperty(navigator, 'language', {
        get: () => 'zh-CN',
        configurable: true
    });
    
    Object.defineProperty(navigator, 'platform', {
        get: () => 'Win32',
        configurable: true
    });
    
    Object.defineProperty(navigator, 'hardwareConcurrency', {
        get: () => 8,
        configurable: true
    });
    
    Object.defineProperty(navigator, 'deviceMemory', {
        get: () => 8,
        configurable: true
    });
    
    // 4. 修改 userAgentData（修复 Chrome for Testing 检测）
    if (navigator.userAgentData) {
        const originalGetHighEntropyValues = navigator.userAgentData.getHighEntropyValues?.bind(navigator.userAgentData);
        if (originalGetHighEntropyValues) {
            navigator.userAgentData.getHighEntropyValues = function(hints) {
                return originalGetHighEntropyValues(hints).then(values => {
                    if (values.brands) {
                        values.brands = values.brands.map(brand => {
                            if (brand.brand === 'Chromium') {
                                return { brand: 'Google Chrome', version: brand.version };
                            }
                            return brand;
                        });
                    }
                    return values;
                });
            };
        }
        
        Object.defineProperty(navigator.userAgentData, 'brands', {
            get: () => [
                { brand: 'Google Chrome', version: '122' },
                { brand: 'Not;A=Brand', version: '8' }
            ],
            configurable: true
        });
        
        Object.defineProperty(navigator.userAgentData, 'platform', {
            get: () => 'Windows',
            configurable: true
        });
    }
    
    // 5. WebGL 指纹修改
    const getParameter = WebGLRenderingContext.prototype.getParameter;
    WebGLRenderingContext.prototype.getParameter = function(parameter) {
        if (parameter === 37445) { // UNMASKED_VENDOR_WEBGL
            return 'Intel Inc.';
        }
        if (parameter === 37446) { // UNMASKED_RENDERER_WEBGL
            return 'Intel Iris OpenGL Engine';
        }
        return getParameter(parameter);
    };
    
    // 6. Canvas 指纹修改
    const toBlob = HTMLCanvasElement.prototype.toBlob;
    const toDataURL = HTMLCanvasElement.prototype.toDataURL;
    
    const getRandomNoise = (() => {
        const noise = Math.random() * 0.0001;
        return () => noise;
    })();
    
    HTMLCanvasElement.prototype.toBlob = function(callback, type, quality) {
        const canvas = this;
        const ctx = canvas.getContext('2d');
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        for (let i = 0; i < imageData.data.length; i += 4) {
            imageData.data[i] += getRandomNoise();
        }
        ctx.putImageData(imageData, 0, 0);
        return toBlob.apply(canvas, arguments);
    };
    
    HTMLCanvasElement.prototype.toDataURL = function(type, quality) {
        const canvas = this;
        const ctx = canvas.getContext('2d');
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        for (let i = 0; i < imageData.data.length; i += 4) {
            imageData.data[i] += getRandomNoise();
        }
        ctx.putImageData(imageData, 0, 0);
        return toDataURL.apply(canvas, arguments);
    };
    
    // 7. AudioContext 指纹修改
    const AudioContext = window.AudioContext || window.webkitAudioContext;
    if (AudioContext) {
        const originalCreateAnalyser = AudioContext.prototype.createAnalyser;
        AudioContext.prototype.createAnalyser = function() {
            const analyser = originalCreateAnalyser.apply(this, arguments);
            const getFloatFrequencyData = analyser.getFloatFrequencyData;
            analyser.getFloatFrequencyData = function(array) {
                getFloatFrequencyData.apply(this, arguments);
                for (let i = 0; i < array.length; i++) {
                    array[i] += getRandomNoise();
                }
            };
            return analyser;
        };
    }
    
    // 8. 删除自动化相关属性
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol;
    
    console.log('[Stealth] CDP 反检测脚本已加载（完整版本，已验证通过 Fingerprint.com）');
'''

# Playwright 反检测 JavaScript 脚本（用于 add_init_script，降级方案）
PLAYWRIGHT_STEALTH_SCRIPT = """
(() => {
    // ========== 1. navigator.webdriver 处理 ==========
    // ⚠️ 关键：正常浏览器中，navigator.webdriver **完全不存在**（检测显示 "No webdriver presented."）
    // 不是 false，不是 undefined，而是属性完全不存在
    //
    // ⚠️ 重要：我们不能删除 navigator.webdriver（会变成 undefined，检测工具会说被手动删除）
    // 也不能添加 webdriver（会被 Object.getOwnPropertyNames 检测到）
    // 也不能清理原型链（可能会影响 webdriver 的状态）
    // 
    // 解决方案：**完全不处理 webdriver**，完全依赖启动参数（--disable-blink-features=AutomationControlled）
    // 让浏览器和启动参数处理，这个脚本不碰 webdriver
    //
    // ⚠️ 注意：以下代码已被移除，完全依赖启动参数
    // 之前的 delete navigator.__proto__.webdriver 和 delete navigator.webdriver 都会导致问题
    
    // ========== 2. 模拟 Chrome runtime ==========
    if (!window.chrome) {
        window.chrome = {};
    }
    if (!window.chrome.runtime) {
        window.chrome.runtime = {
            PlatformOs: {
                MAC: 'mac',
                WIN: 'win',
                ANDROID: 'android',
                CROS: 'cros',
                LINUX: 'linux',
                OPENBSD: 'openbsd'
            },
            PlatformArch: {
                ARM: 'arm',
                X86_32: 'x86-32',
                X86_64: 'x86-64'
            },
            PlatformNaclArch: {
                ARM: 'arm',
                X86_32: 'x86-32',
                X86_64: 'x86-64'
            },
            RequestUpdateCheckStatus: {
                THROTTLED: 'throttled',
                NO_UPDATE: 'no_update',
                UPDATE_AVAILABLE: 'update_available'
            },
            OnInstalledReason: {
                INSTALL: 'install',
                UPDATE: 'update',
                CHROME_UPDATE: 'chrome_update',
                SHARED_MODULE_UPDATE: 'shared_module_update'
            },
            OnRestartRequiredReason: {
                APP_UPDATE: 'app_update',
                OS_UPDATE: 'os_update',
                PERIODIC: 'periodic'
            }
        };
    }
    
    // ========== 3. 模拟真实的 navigator.plugins ==========
    // ⚠️ 注意：不要使用 Object.defineProperty，会被 Object.getOwnPropertyNames 检测到
    // 如果 Playwright 已经有这些属性，不要覆盖它们
    // 只在缺失时尝试添加（但风险是被检测到）
    // 最好的方法是依赖浏览器原生属性，不做任何修改
    Object.defineProperty(navigator, 'webdriver', {
        get: () => false  // or false
    });
    // ⚠️ 移除：Object.defineProperty(navigator, 'plugins', ...)
    // ⚠️ 移除：Object.defineProperty(navigator, 'mimeTypes', ...)
    // 这些会被 Object.getOwnPropertyNames 检测到
    
    // ========== 5. 覆盖 permissions API ==========
    const originalQuery = window.navigator.permissions.query;
    window.navigator.permissions.query = (parameters) => (
        parameters.name === 'notifications' ?
            Promise.resolve({ state: Notification.permission }) :
            originalQuery(parameters)
    );
    
    // ========== 6. 设置语言和平台 ==========
    // ⚠️ 移除：不要使用 Object.defineProperty 添加这些属性
    // 它们会被 Object.getOwnPropertyNames 检测到
    // 依赖浏览器原生属性，不做修改
    
    // ========== 7. 覆盖 navigator.userAgentData（修复 Chrome for Testing 检测） ==========
    // ⚠️ 注意：修改 userAgentData 方法可能可以，但不要使用 Object.defineProperty
    // 因为 Object.getOwnPropertyNames 不会检测方法覆盖，只会检测属性定义
    if (navigator.userAgentData) {
        const originalGetHighEntropyValues = navigator.userAgentData.getHighEntropyValues?.bind(navigator.userAgentData);
        if (originalGetHighEntropyValues) {
            navigator.userAgentData.getHighEntropyValues = function(hints) {
                return originalGetHighEntropyValues(hints).then(values => {
                    // 将 "Chromium" 替换为 "Google Chrome"
                    if (values.brands) {
                        values.brands = values.brands.map(brand => {
                            if (brand.brand === 'Chromium') {
                                return { brand: 'Google Chrome', version: brand.version };
                            }
                            return brand;
                        });
                    }
                    return values;
                });
            };
        }
        
        // ⚠️ 移除：不要使用 Object.defineProperty 覆盖 userAgentData 的属性
        // 这会被 Object.getOwnPropertyNames 检测到
    }
    
    // ========== 8. 硬件和连接信息 ==========
    // ⚠️ 移除：不要使用 Object.defineProperty 覆盖这些属性
    // 它们会被 Object.getOwnPropertyNames 检测到
    // 依赖浏览器原生属性，不做修改
    
    // ========== 10. 覆盖 WebGL 供应商和渲染器（避免检测） ==========
    const getParameter = WebGLRenderingContext.prototype.getParameter;
    WebGLRenderingContext.prototype.getParameter = function(parameter) {
        if (parameter === 37445) { // UNMASKED_VENDOR_WEBGL
            return 'Intel Inc.';
        }
        if (parameter === 37446) { // UNMASKED_RENDERER_WEBGL
            return 'Intel Iris OpenGL Engine';
        }
        return getParameter(parameter);
    };
    
    // ========== 11. 覆盖 Canvas 指纹（避免被检测） ==========
    const toBlob = HTMLCanvasElement.prototype.toBlob;
    const toDataURL = HTMLCanvasElement.prototype.toDataURL;
    const getImageData = CanvasRenderingContext2D.prototype.getImageData;
    
    // 添加少量随机噪声（但保持一致性）
    const getRandomNoise = (() => {
        const noise = Math.random() * 0.0001;
        return () => noise;
    })();
    
    HTMLCanvasElement.prototype.toBlob = function(callback, type, quality) {
        const canvas = this;
        const ctx = canvas.getContext('2d');
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        for (let i = 0; i < imageData.data.length; i += 4) {
            imageData.data[i] += getRandomNoise();
        }
        ctx.putImageData(imageData, 0, 0);
        return toBlob.apply(canvas, arguments);
    };
    
    HTMLCanvasElement.prototype.toDataURL = function(type, quality) {
        const canvas = this;
        const ctx = canvas.getContext('2d');
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        for (let i = 0; i < imageData.data.length; i += 4) {
            imageData.data[i] += getRandomNoise();
        }
        ctx.putImageData(imageData, 0, 0);
        return toDataURL.apply(canvas, arguments);
    };
    
    // ========== 12. 覆盖 AudioContext 指纹 ==========
    const AudioContext = window.AudioContext || window.webkitAudioContext;
    if (AudioContext) {
        const originalCreateAnalyser = AudioContext.prototype.createAnalyser;
        AudioContext.prototype.createAnalyser = function() {
            const analyser = originalCreateAnalyser.apply(this, arguments);
            const getFloatFrequencyData = analyser.getFloatFrequencyData;
            analyser.getFloatFrequencyData = function(array) {
                getFloatFrequencyData.apply(this, arguments);
                for (let i = 0; i < array.length; i++) {
                    array[i] += getRandomNoise();
                }
            };
            return analyser;
        };
    }
    
    // ========== 13. 隐藏自动化相关属性 ==========
    // 删除所有可能暴露自动化的属性
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol;
    
    // ========== 14. 覆盖 Notification 权限 ==========
    // ⚠️ 移除：虽然 Notification 不是 navigator，但为了一致性也移除
    
    console.log('[Stealth] 反检测脚本已加载');
})();
"""

